#ifndef INC_PHP_H
#define INC_PHP_H

#define PHP_METHOD(CLASS, METHOD)  void CLASS ## METHOD () 
#define PHP_FUNCTION(METHOD)  void GLOBAL_ ## METHOD () 
/*
 'class zend_function' has no member named 'common'

/*
*/
class ZValField
{

};

class  zvalR2 : public ZValField
{
 public:
  operator bool ();
  template <class A> bool operator == (A &) ;
  template <class A> zvalR2& operator = (A &) ;
  zvalR2& operator = (int) ;

};
class  zvalC2 : public ZValField
{
public:
  zvalC2 & operator ++ ();
  zvalC2 & operator ++ (int);
  zvalC2 & operator -- ();
  zvalC2 & operator -- (int);
  template <class A> zvalC2& operator = (A &) ;  
};
class zvalV2HT
{

};
class  zvalV2 : public ZValField
{
 public:
  zvalV2HT ht;
};
class  zvalT2 : public ZValField
{
 public:

  template <class T> bool operator != (T );
};
//  bool operator != (int );

template <class T> static T  MakeNullPtr();
template <class T> static T  MakeNullPtrPtr();

// the 
class zval
{
 public:
  zval();
  zval(const zval & r);
  ~zval();
  zvalR2 is_ref;
  zvalC2 refcount;
  zvalV2 value;
  zvalT2 type;

  // make a null pointer
  //  static zval  MakeNull();
};



class HashTable
{
 public:
  int nNumOfElements;
};

class vakz
{

};





class NULLT 
{ 
 public: 
  NULLT ()
    {
    }
  
  NULLT (int)
    {

    }

  template <class Y> NULLT(Y & rY){
    // create a null object out of some value? well it sould always be null
    
  }

  template <class Y> operator Y**() const
    {
      //      return MakeNullPtrPtr<Y>();
    }

   template <class Y> operator Y*() const
     {
  //   return MakeNullPtr<Y*>();
     }

  /*  template <class Y> operator Y () const
    {
      return Y::MakeNull();
    }
  */

  operator int () const 
  {
    return 0;
  }
};

// derived everything from a zval... 

#define MYSTD(X) class X : public zval {			\
public: \
 X ();  \
 X (const NULLT); \
 X (int);  \
   template <class Y> X(Y & rY); \
   template <class Y> X(Y ** pY); \
   template <class Y> X(const Y ** pY); \
   template <class Y> X(const Y * rY); \
   template <class A,class B> X(A, B);	\
   template <class A,class B,class C> X(A, B, C);	\
   template <class A,class B,class C,class D> X(A, B, C, D);	\
   template <class A,class B,class C,class D,class E> X(A, B, C, D, E);	\
   template <class A,class B,class C,class D,class E,class F> X(A, B, C, D, E, F);	\
   template <class A,class B,class C,class D,class E,class F,class G> X(A,B, C, D, E, F,G); \
   template <class A,class B,class C,class D,class E,class F,class G> X(A*,B*, C, D, E**, F,G); \
   template <class A> operator A () const;				\
   template <class A> operator A () ;						\
   operator int () ;						\
   X operator ++ () ;						\
   X operator ++ (int) ;						\
   X & operator -- ();    \
   X & operator -- (int);  \
   template <class A> A * operator -> () ;						\
   bool operator > (int) ;						\
   bool operator ! () ;						\
   };

/*bool operator == (zend_hash_has_more_elements, int ) 
{

}*/

//   template <class A> bool operator == (const A &) const ;		
   //   template <class A> bool operator == (A &) ;			


// template <class Y,class Z> X(Y &, Z&);	\

extern int x;

MYSTD(STDRET) 

class STDRET2
{
 public: 
  operator int();
};

//   template <class Y> STDRET X(const Y * rY); 
// template <class P> STDRET X (P);		

#define MYSTDF(X)   \
  STDRET X ();				\
template <class P> STDRET X (P*);	\
template <class Y> STDRET X(Y & rY);		\
template <class A,class B> STDRET X(A, B);			\
template <class A,class B,class C> STDRET X(A, B, C);			\
   template <class A,class B,class C,class D> STDRET X(A, B, C, D);	\
   template <class A,class B,class C,class D,class E> STDRET X(A, B, C, D, E);	\
   template <class A,class B,class C,class D,class E,class F> STDRET X(A, B, C, D, E, F);	\

#define MYSTDFP(X)   \
template <class P> STDRET* X (P*);	\
template <class Y> STDRET* X(Y & rY);		\
template <class A,class B> STDRET* X(A, B);			\
template <class A,class B,class C> STDRET *X(A, B, C);			\
   template <class A,class B,class C,class D> STDRET* X(A, B, C, D);	\
   template <class A,class B,class C,class D,class E> STDRET * X(A, B, C, D, E);	\
   template <class A,class B,class C,class D,class E,class F> STDRET * X(A, B, C, D, E, F);	\



extern NULLT stderr;

//template <class R, class P> void X (P&);	


MYSTDF(phc_builtin_empty)
MYSTDF(get_constant)
MYSTDF(phc_setup_error)
MYSTDF(initialize_constructor_call)
MYSTDF(fprintf)
MYSTDF(phc_builtin_print)
MYSTDF(zval_ptr_dtor)
MYSTDF(array_init)
MYSTDF(ALLOC_INIT_ZVAL)
MYSTDF(Z_LVAL_P)
//template <class R, class P> R Z_LVAL_P (P&); 
//template <class R, class P> R Z_LVAL_P (P*);
//template <class R, class P> R Z_LVAL_P (P);


MYSTD(NULLT2)

extern NULLT2 uninitialized_zval_ptr;

MYSTD(CG)

MYSTD(E_ERROR)
MYSTD(E_WARNING)




//MYSTD(TSRMLS_CC)
MYSTD(ZEND_REQUIRE)
MYSTD(ZEND_INCLUDE)
MYSTDF(STR_PRINT)



MYSTD(Z_BVAL_P)
MYSTD(Z_DVAL_P)


MYSTD(assert)
MYSTD(compiled_filename)
MYSTD(erealloc)
MYSTD(fci)
MYSTD(fcic)


MYSTD(function_state_ptr)
MYSTD(in_compilation)
MYSTD(in_execution)

MYSTDF(initialize_function_call)
MYSTDF(is_ref)
MYSTD(memset)
MYSTD(old_function)
MYSTDF(php_error_docref)
MYSTD(printf)
MYSTD(stderr)
MYSTDF(strlen)
MYSTD(type)
MYSTD(ulong)
MYSTD(uninitialized_zval_ptr)
MYSTD(value)
MYSTD(zend_fcall_infoB)
MYSTD(arg_info)


MYSTDF(ZEND_NUM_ARGS);

//MYSTDF(HASH_KEY_NON_EXISTANT)
MYSTD(HashPosition)
MYSTDF(zend_hash_internal_pointer_reset_ex)

MYSTDF(initialize_method_call)
MYSTDF(ZEND_NUM_ARGS)
MYSTDF(ZVAL_NULL)
MYSTDF(add_function)
MYSTDF(bitwise_and_function)
MYSTDF(bitwise_not_function)
MYSTDF(boolean_not_function)
MYSTDF(concat_function)
MYSTDF(convert_to_boolean)
MYSTDF(div_function)
MYSTD(ht_iterator35472)
MYSTD(ht_iterator35589)
MYSTDF(increment_function)
MYSTDF(is_equal_function)
MYSTDF(is_identical_function)
MYSTDF(is_not_equal_function)
MYSTDF(is_not_identical_function)
MYSTDF(is_smaller_function)
MYSTDF(is_smaller_or_equal_function)
MYSTDF(mod_function)
MYSTDF(mul_function)
MYSTDF(object_init_ex)
MYSTDF(safe_free_zval_ptr)
MYSTDF(shift_left_function)
MYSTDF(str_length)
MYSTDF(sub_function)
MYSTD(uint)

//MYSTDF(zend_call_function)
//TSTDRET zend_call_function (); 
//template <class P> STDRET zend_call_function (P*); 
//template <class Y> STDRET zend_call_function(Y & rY); 
template <class T> class STDRETT
{
 public:
  operator T();
};

template <class A,class B> STDRETT<int> zend_call_function(A*, B*); 
//template <class A,class B,class C> STDRET zend_call_function(A, B, C); 
//template <class A,class B,class C,class D> STDRET zend_call_function(A, B, C, D); 
//template <class A,class B,class C,class D,class E> STDRET zend_call_function(A, B, C, D, E); 
//template <class A,class B,class C,class D,class E,class F> STDRET zend_call_function(A, B, C, D, E, F);

MYSTDF(zend_fetch_class)
MYSTDF(zend_get_parameters_array)
MYSTDF(zend_hash_get_current_data_ex)
MYSTDF(zend_hash_get_current_key_type_ex)
MYSTDF(zend_hash_internal_pointer_end_ex)
MYSTDF(zend_hash_internal_pointer_reset_ex)
MYSTDF(zend_hash_move_forward_ex)
MYSTDF(zend_is_true)


MYSTD(zend_functionB)
MYSTD(zend_functionPC)
MYSTD(zend_functionPS)
MYSTD(zend_functionR)
MYSTD(zend_functionC2)


MYSTD(zend_functionCArg)
MYSTD(zend_functionCPass)
MYSTD(zend_functionCReturn)
MYSTD(zend_function_name)

class zend_functionC : public zend_functionC2
{
 public:
  zend_function_name  function_name;
  zend_functionCArg    arg_info;
  zend_functionCPass   pass_rest_by_reference;
  zend_functionCReturn return_reference;
};

MYSTD(zend_arg_infoB)
MYSTD(zend_arg_infoR)
class zend_arg_info 
{
 public:
  zend_arg_infoR pass_by_reference;
};

class zend_fcall_info :public zend_fcall_infoB
{
public:
  //  'class zend_fcall_info' has no member named 'param_count'
  // 'class zend_fcall_info' has no member named 'params'
  // 'class zend_fcall_info' has no member named 'retval_ptr_ptr'
  zend_functionPC param_count;
  zend_functionPS params;
  zend_functionR  retval_ptr_ptr;
};

template <class F> class zend_functionPCT  : public zend_functionPC
{
 public:
  zend_functionPCT<F> & operator=(int) const
  {
  // this has got to be one...
  };

};


MYSTD(zend_hash_del)
MYSTD(zend_hash_exists)
MYSTD(zend_hash_find)
MYSTDF(zend_hash_get_current_data)
MYSTDF(zend_hash_get_current_key_ex)
MYSTDF(zend_hash_has_more_elements)
MYSTDF(zend_hash_index_del)
MYSTDF(zend_hash_index_exists)
MYSTDF(zend_hash_index_find)
MYSTDF(zend_hash_index_update)
MYSTDF(zend_hash_internal_pointer_reset)
MYSTDF(zend_hash_move_forward)
MYSTDF(zend_hash_next_index_insert)
MYSTDF(zend_hash_quick_add)
MYSTDF(zend_hash_quick_find)
MYSTDF(zend_hash_update)
MYSTD(zend_lineno)
MYSTD(zend_bool)

MYSTDF(zend_symtable_find)
MYSTDF(zend_symtable_update)

#define TSRMLS_DC 
#define TSRMLS_CC

MYSTDF(zval_dtor)


/// FUNCIONT
MYSTDF(MAKE_STD_ZVAL)
MYSTDF(zval_copy_ctor)

MYSTDF(convert_to_array)
MYSTDF(convert_to_long)
MYSTDF(convert_to_string)


MYSTD(Z_ARRVAL_P_T)

//typedef Z_ARRVAL_P_T* Z_ARRVAL_P;
typedef HashTable * Z_ARRVAL_P;


#define MYSTDV(X) const NULLT X;

MYSTDF(ALLOC_HASHTABLE)
MYSTDV(BP_VAR_R)
MYSTDV(E_ERROR)
MYSTDV(E_WARNING)
       MYSTDV(E_ALL)
       MYSTDV(E_NOTICE)
MYSTDF(FREE_HASHTABLE)
MYSTDF(INIT_ZVAL)
MYSTDF(TODO)
MYSTDV(ZEND_ACC_PRIVATE)
MYSTDV(ZEND_ACC_PROTECTED)
MYSTDV(ZEND_ACC_STATIC)




MYSTDV(ZEND_ACC_PUBLIC)
MYSTDV(ZEND_USER_FUNCTION)
MYSTDV(ZEND_FETCH_CLASS_DEFAULT)
MYSTDV(HASH_KEY_NON_EXISTANT)
MYSTDV(NULL)
MYSTDV(SUCCESS)
MYSTDV(HASH_KEY_IS_STRING)


MYSTDF(assign_expr_instanceOfMyVariable)
MYSTDF(bitwise_or_function)
MYSTDF(boolean_xor_function)
MYSTDF(convert_to_double)
MYSTDF(convert_to_object)
MYSTDF(decrement_function)
MYSTDF(phc_check_invariants)
MYSTDF(return_value_ptr)
MYSTDF(shift_right_function)
MYSTDF(zend_hash_destroy)
MYSTDF(zend_hash_init)
MYSTDF(zend_read_static_property)
MYSTDF(zend_std_get_static_property)
MYSTDF(zend_update_static_property)
MYSTDF(get_st_entry);

/*
MYSTDV(IS_ARRAY)
MYSTDV(IS_BOOL)
MYSTDV(IS_DOUBLE)
MYSTDV(IS_LONG)
MYSTDV(IS_OBJECT)
MYSTDV(IS_RESOURCE)
MYSTDV(IS_STRING)
*/

class T
{
 public:
  T(int);
  T();
  operator int () const ;
};


const int IS_NULL=0;
const int IS_LONG=1;
const int IS_BOOL=2;
const int IS_DOUBLE=3;
const int IS_ARRAY=4;
const int IS_OBJECT=5;
const int IS_STRING=6;
const int IS_RESOURCE=7;

//MYSTD(zend_fcall_info_cache_T)

//zend_fcall_info_cache_T [] zend_fcall_info_cache;
//

//class zvalVHT{};
class zvalV{
 public :
  HashTable* ht;
};

class return_valueV
{
 public :
  template <class T> return_valueV & operator=(T &v);
};

class return_valueT
{
 public:
  template <class T> return_valueV & operator=(T &v);
};

class return_valueT2
{
 public :
  return_valueV value;
  return_valueT type;
};

// global
extern return_valueT2 * return_value;

MYSTD(zvalR)
MYSTD(zvalT)
MYSTD(zvalC)

class zvalImp
{
 public:
  zvalR is_ref;
  zvalC refcount;
  zvalV value;
  zvalT type;
};



MYSTD(zend_class_entryB)
MYSTD(zend_class_entry_name)

class zend_class_entry : public zend_class_entryB
{
 public:
  zend_class_entry_name  name;
  //  static  zend_class_entry * MakeNull();// make a null object?
  template <class T> static T*  MakeNullPtr();
  template <class T> static T**  MakeNullPtrPtr();
};

extern int removethissthing;

class BEGIN_ARG_INFO_EX
{
 public:
  /*
    template <class A,
    class B,
    class C>*/
  BEGIN_ARG_INFO_EX(int A, int B, int C, STDRET);
  BEGIN_ARG_INFO_EX(int A, int B, int C, STDRET,STDRET);
  BEGIN_ARG_INFO_EX(int A, int B, int C, STDRET,STDRET,STDRET);
  BEGIN_ARG_INFO_EX(int A, int B, int C, STDRET,STDRET,STDRET,STDRET);
  BEGIN_ARG_INFO_EX(int A, int B, int C, STDRET,STDRET,STDRET,STDRET,STDRET);
  BEGIN_ARG_INFO_EX(int A, int B, int C, STDRET,STDRET,STDRET,STDRET,STDRET,STDRET);
  BEGIN_ARG_INFO_EX(int A, int B, int C, STDRET,STDRET,STDRET,STDRET,STDRET,STDRET,STDRET);
  BEGIN_ARG_INFO_EX(int A, int B, int C, STDRET,STDRET,STDRET,STDRET,STDRET,STDRET,STDRET,STDRET);
  BEGIN_ARG_INFO_EX(int A, int B, int C, STDRET,STDRET,STDRET,STDRET,STDRET,STDRET,STDRET,STDRET,STDRET);
  BEGIN_ARG_INFO_EX(int A, int B, int C, STDRET,STDRET,STDRET,STDRET,STDRET,STDRET,STDRET,STDRET,STDRET,STDRET);
  BEGIN_ARG_INFO_EX(int A, int B, int C);
  BEGIN_ARG_INFO_EX(NULLT);
    
};


#define ZEND_BEGIN_ARG_INFO_EX(X,A,B,C)  BEGIN_ARG_INFO_EX X(A,B,C /**more stuff follows*/

MYSTDF(ZEND_ARG_INFOIMP)

#define ZEND_ARG_INFO(X,Y) ,ZEND_ARG_INFOIMP(X,Y)


#define ZEND_END_ARG_INFO() ); /**end of arguments to constructor...*/

MYSTD(Myfunction_entry)
//MYSTD(function_entry)

class GetDBT
{
};

extern GetDBT GetDB;


class  CreateObject
{
 public:
  CreateObject(NULLT);
  template <class A,class B> CreateObject (const char *, const char*, A,B);
  CreateObject (const char *, const char*);
};

class function_entry
{
 public:
  CreateObject First;
  BEGIN_ARG_INFO_EX arginfo;
  NULLT access;
};


#define PHP_ME(CLASS, METHOD, C ,D) \
  {CreateObject(#CLASS , #METHOD) ,C,D},

MYSTDV(HASH_KEY_IS_LONG)


MYSTDF(MYSsymbol_table)
MYSTDF(MyArray_next)
MYSTDF(MyUnset)


MYSTD(symbol_tableT)

extern symbol_tableT symbol_table;// global value 
extern symbol_tableT active_symbol_table;


MYSTDF(bitwise_xor_function)
MYSTDF(zend_hash_add)



MYSTD(class_table_t) 
extern class_table_t class_table;

MYSTD(function_table_t) 
extern function_table_t function_table;

// for everything else
class zvalP
{
 public:
  zvalP(const NULLT);
  zvalP(zval*);
  zvalP();
  //operator -> () ; 
  zval * operator->();
  zval & operator * (); 
  //  template <class A> A  operator -> () ; 
  //  template <class A> A  operator * () ; 
  zvalP & operator=(const zvalP&);
  template <class T> bool operator != (T );
  template <class T> bool operator == (T );
  template <class T> bool operator = (T );
  operator zval* ( );
  //bool operator ! (class & A );
};
//typedef zval
// for return values

typedef zvalP   zvalPA;

template <class F> class zend_functionRTP
{
  
};

class zvalPP
{
 public:
  zvalPP();
  zvalPP(zval**);
  zvalPP(zvalPA*);
  template <class A> A  operator -> () ;
  template <class A> A  operator * () ; 
  zvalPP & operator=(const zvalPP&);
  zvalP  operator*();
  operator zval**();

  /*
    the user of this class, uses this as return type.
    so, how can we store this fact?
  */
  template <class F> static void setReturnType()
    {
      //const zend_functionRTP<F> * pFunction
      // this object is being used as the return type of the class  F      
    }
  //  template <class A> bool operator ! (class & A );
};


/**
   this class is a return type of a class
*/


template <class T> class zvalPPReturn : public zvalPP
{
 public:
  //
  template <class F> static void setReturnType()
    {
      // this object is being used as the return type of the class  F
    }
};

//zvalPReturn<mwnamespace_getcanonicalname>::setReturnType() const

template <class T, class G>
 void setReturnTypeDynamicT(const T &, G  val);

template <class T> class zvalPReturn : public zvalP
{
 public:
  zvalPReturn(const NULLT&)    {    }
  
  //  zvalPReturn & operator=(const NULLT&) {}
    
  static void setReturnType() 
  {
    // this object is being used as the return type of the class  F
  }
  
  template <class G> void setReturnTypeDynamic(G val)  const
  {
    // setReturnTypeDynamicT<T,G>(*this,val);

    //»setReturnTypeDynamicT(const zvalPReturn<mwnamespace_getcanonicalname>&, 
    //			   zend_functionRT<mwnamespace_getcanonicalname>*&)«

  }
  
  /*
  // dynamic
  template <class F> void setReturnType() const
    {
      // this object is being used as the return type of the class  F
    }
  */
};

typedef zvalPP  zvalPPA;
// pointer pointer pointer for arguments
class zvalPPP
{
  template <class A> A  operator -> () ; 
  template <class A> A  operator * () ; 
  zvalPPP & operator=(const zvalPPP&);
  //  template <class A> bool operator ! (class & A );
};

/**
 error: new declaration 'void phc_check_invariants()'

*/
template <class Y> 
class SmartRet  {
 public:
  Y* operator & ();
  operator zval * ();
  operator zvalP ();
  operator bool ();

};

template <class Y> SmartRet<Y> EG(Y * pY);		
template <class Y> SmartRet<Y> EG(Y & pY);		


//MYSTDFP(Z_BVAL_PP)
//MYSTD(Z_LVAL_PP)
//MYSTD(Z_OBJPROP_P)
MYSTDF(Z_STRLEN_P)
MYSTDF(Z_STRLEN_PP)
MYSTDF(Z_STRVAL_P) // string
//MYSTD(Z_STRVAL_PP)
MYSTDF(Z_TYPE_P)
MYSTDF(Z_TYPE_PP)
MYSTDF(ZVAL_DOUBLE)
MYSTDF(ZVAL_PTR_DTOR)
MYSTDF(ZVAL_STRING)
MYSTDF(ZVAL_IS_NULL)
MYSTDF(ZVAL_LONG)
MYSTDF(ZVAL_BOOL)
MYSTDF(ZVAL_STRINGL)
MYSTDF(PZVAL_IS_REF)


#define MYSTDFP2(X,Y)							\
  template <class P>							\
    Y * X(P*);								\
  template <class A>							\
    Y * X(A & rY);							\
  template <class A,class B>						\
    Y * X(A, B);							\
  template <class A,class B,class C>					\
    Y * X(A, B, C);							\
  template <class A,class B,class C,class D>				\
    Y * X(A, B, C, D);							\
  template <class A,class B,class C,class D,class E>			\
    Y * X(A, B, C, D, E);						\
  template <class A,class B,class C,class D,class E,class F>		\
    Y * X(A, B, C, D, E, F);						



//MYSTDF(in_copy_on_write)


class Z_OBJ_HT_PP_RET : public STDRET
{
 public:
  MYSTDF(get_property_ptr_ptr)
    MYSTDF(read_property)
    MYSTDF(write_property)
    void f();
};

//int x;
MYSTDFP2(Z_OBJ_HT_PP,Z_OBJ_HT_PP_RET)
//int y;

/**
   simple replacements on zval 

*/


/*
class zvalPPA
{
  zvalP& operator*()           ;
  zvalP* operator->()         ;
  }*/

  template <class T,class G>
  void DoAssign(T,G);

// params
template <class F>  class zend_functionPST : public zend_functionPS
{
  //class zend_functionPS : public zval { 
 public: 
  // set the arguments value
  //zend_functionPST <F> & operator = (zval ***); 
   //   zend_functionPST <F> & operator = (zvalPPP); 
   //   zend_functionPST <F> & operator = (zvalPPA *); 
   zend_functionPST <F> & operator = (zvalPPA ); 
   
   // generic template parameter
   template <class T> zend_functionPST <F> & operator = (T t)
     {
       DoAssign(*this,t);
     }
};

template <class F> class zend_functionRT : public zend_functionR
{
 public:

  /*
    here we have the generic one, now we tighten it down.
  */
  /*  zend_functionRT <F> & operator = (const zvalPP & rP)
    {
      //we have a parameter, now we assert the types.
      rP.setReturnType<F>(); // this means that the parameter needs this type
    }
  */

  //operator zend_functionRTP<F> ();

  
  zend_functionRT <F> & operator = (const zvalPPReturn<F> & rP)
    {
      //we have a parameter, now we assert the types.
      rP.setReturnType(); // this means that the parameter needs this type
    }
  zend_functionRT <F> & operator = (const zvalPReturn<F> * pP)
    {
      //we have a parameter, now we assert the types.
      //pP->setReturnType(); // this means that the parameter needs this type
      //zvalPReturn<F>::setReturnType();
      pP->setReturnTypeDynamic(this);
    }

  zend_functionRT<T>&    operator=
    /*<zvalPReturn<mwnamespace_getcanonicalname>*>*/
    (zvalPReturn<T>*)
    {
    };
  //  zend_functionRT<mwnamespace_getcanonicalname>& zend_functionRT<mwnamespace_getcanonicalname>::operator=<zval**>(zval**){};

//  template <class T>  zend_functionRT <F> & operator = (T);
  
};


template <class Function> 
class zend_fcall_infoT //: public zend_fcall_info
{
 public:
  zend_functionPCT<Function> param_count;
  zend_functionPST<Function> params;
  zend_functionRT<Function>  retval_ptr_ptr;
  /**
     this is 
   */
};
// for the call by variable
extern zend_fcall_info TODO_fcic;

class zend_function : public zend_functionB
{
public:
  zend_functionPC param_count;
  zend_functionPS params;
  zend_functionR  retval_ptr_ptr;
  zend_functionC  common;

  //  static  zend_function * MakeNull();// make a null object?
  template <class T> static T*  MakeNullPtr();
  template <class T> static T**  MakeNullPtrPtr();
};

typedef struct _zend_fcall_info_cache {
        zend_bool initialized;
        zend_function *function_handler;
        zend_class_entry *calling_scope;
        zval **object_pp;
} zend_fcall_info_cache;

template <class T> class zend_fcall_info_cacheT: public _zend_fcall_info_cache
{
  /**
     template static method call
   */
};

template <class T> class zvalParamsT 
{

};

#endif
